<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>无规则裁剪</title>
</head>

<body style="margin: 0">
    <canvas id="cvs" style="width: 400px;"></canvas>
</body>
<script>
    const cvs = document.getElementById('cvs')
    const ctx = cvs.getContext('2d')
    const lines = []
    const maxW = 400
    const img = new Image()
    img.src = './images/girl2.png'
    img.onload = () => {
        let width = img.width
        let height = img.height
        if (width > maxW) {
            height = maxW / width * height
            width = maxW
        }
        cvs.width = width
        cvs.height = height
        render()
    }
    
    let isMoving = false
    cvs.onmousedown = (e) => {
        isMoving = true
        lines.push({
            mx: e.pageX,
            my: e.pageY,
            lx: e.pageX,
            ly: e.pageY
        })
        render()
    }
    cvs.onmousemove = (e) => {
        if (isMoving) {
            lines[lines.length - 1].lx = e.pageX
            lines[lines.length - 1].ly = e.pageY
            lines[lines.length - 1].isMoving = true
            
        }
    }
    document.onkeyup = (e) => {
        if (e.key.toLocaleLowerCase() === 'enter') {
            isMoving = false
            if (lines[lines.length - 1].isMoving) {
                lines.pop()
            }
            // 裁剪
            setTimeout(async () => {
                lines.forEach((v, i) => {
                    if (i === 0) {
                        ctx.moveTo(v.mx, v.my)  
                    }
                    ctx.lineTo(v.lx, v.ly)
                })
                ctx.clearRect(0, 0, cvs.width, cvs.height)
                ctx.clip()
                ctx.drawImage(img, 0, 0, cvs.width, cvs.height)
                const res = await fetch(cvs.toDataURL('image/png'))
                const blob = await res.blob()
                const a = document.createElement('a')
                a.setAttribute('download', 'clip.png')
                a.href = URL.createObjectURL(blob)
                a.click()
            }, 100)
        }
    }
    const render = () => {
        ctx.clearRect(0, 0, cvs.width, cvs.height)
        ctx.beginPath()
        ctx.drawImage(img, 0, 0, cvs.width, cvs.height)
        ctx.strokeStyle = 'rgba(255, 0, 0, 0.7)'
        lines.forEach((v, i) => {
            if (i === 0) {
                ctx.moveTo(v.mx, v.my)  
            }
            ctx.lineTo(v.lx, v.ly)
        })
        ctx.stroke()
        if (isMoving) {
            requestAnimationFrame(render)
        }
    }
    
    
    
</script>

</html>